#pragma once

#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <jsoncpp/json/json.h>

// #define SELF 1

const std::string sep = "\r\n";
bool Encode(std::string &message)
{
    if (message.empty())
        return false;
    message = std::to_string(message.size()) +
              sep + message + sep;

    return true;
}
bool Decode(std::string &package, std::string *content)
{
    auto pos = package.find(sep);
    if (pos == std::string::npos)
        return false;
    std::string content_length_str = package.substr(0, pos);
    int content_length = std::stoi(content_length_str);
    int full_length = content_length_str.size() +
                      2 * sep.size() + content_length;
    // ! 重要的是我们需要确认报文的完整性
    if (package.size() >= full_length)
    {
        *content = package.substr(pos + sep.size(), content_length);
        package.erase(0, full_length); // * 写网络代码的时候再进行研究的
        return true;
    }
    else
        return false;
}
class Request
{
private:
    double _x, _y;
    char _oper;

public:
    Request(double x, double y, char oper) : _x(x),
                                             _y(y),
                                             _oper(oper)
    {
    }
    Request() : _x(0), _y(0), _oper('+') {}
// 结构化数据 x oper y
    bool Serialize(std::string &out_string)
    {
#ifdef SELF
        std::string x_str = std::to_string(_x);
        std::string y_str = std::to_string(_y);
        out_string = x_str + sep + _oper + sep + y_str;
        return true;
#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::StreamWriterBuilder wb;
        std::unique_ptr<Json::StreamWriter> w(wb.newStreamWriter());
        std::stringstream ss;
        w->write(root, &ss);
        out_string = ss.str();
        return true;
#endif // SELF;
    }


    bool Deserialize(std::string &in_string)
    {
#ifdef SELF
        // "x oper y"
        auto left = in_string.find(sep);
        if (left == std::string::npos) return false;
        auto right = in_string.rfind(sep);
        if (right == std::string::npos) return false;
        if (left + sep.size() + 1 == right)
        {
            auto left_data = in_string.substr(0, left);
            if (left_data.empty()) return false;
            auto right_data = in_string.substr(right + sep.size());
            if (right_data.empty()) return false;


            _oper = in_string[right - 1];
            _x = std::stod(left_data);
            _y = std::stod(right_data);

            return true;
        }
        else return false;
#else
        Json::Value root;
        Json::Reader reader;
        bool parsingSuccessful = reader.parse(in_string, root);
        if (!parsingSuccessful)
        {
            std::cout << "Failed to parse Json: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }
        _x = root["x"].asDouble();
        _y = root["y"].asDouble();
        _oper = root["oper"].asInt();
        return true;
#endif 
    }
    void print()
    {
        std::cout << _x << std::endl;
        std::cout << _oper << std::endl;
        std::cout << _y << std::endl;
    }
    double X() const { return _x; }
    double Y() const { return _y; }
    char Oper() const { return _oper; }
};

class Response
{
private:
    double _ret; //* 结果
    int _code;   //* 错误码
public:
    Response() : _ret(0), _code(0)
    {
    }
    void setResult(double &&res) { _ret = res; }
    void setCode(int code) { _code = code; }
    bool Serialize(std::string &out_string)
    {
#ifdef SELF
        std::string result_str = std::to_string(_ret);
        auto code_str = std::to_string(_code);
        out_string = result_str + sep + code_str;
        return true;
#else
        Json::Value root;
        root["ret"] = _ret;
        root["code"] = _code;

        Json::StreamWriterBuilder wb;
        std::unique_ptr<Json::StreamWriter> w(wb.newStreamWriter());
        std::stringstream ss;
        w->write(root, &ss);
        out_string = ss.str();
        return true;
#endif // SELF
    }
    bool Deserialize(std::string &in_string)
    {
#ifdef SELF
        auto mid = in_string.find(sep);
        if (mid == std::string::npos) return false;
        auto left_data = in_string.substr(0, mid);
        auto right_data = in_string.substr(mid + sep.size());
        if (left_data.empty() || right_data.empty()) return false;

        _ret = std::stod(left_data);
        _code = std::stod(right_data);

        return false;

#else
        Json::Value root;
        Json::Reader reader;
        bool parsingSuccessful = reader.parse(in_string, root);
        if (!parsingSuccessful)
        {
            std::cout << "Failed to parse Json: " << reader.getFormattedErrorMessages() << std::endl;
            return false;
        }
        _ret = root["ret"].asDouble();
        _code = root["code"].asInt();
        return true;
#endif // SELF
    }
    double Ret() { return _ret; }
    int Code() { return _code; }
};

// deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
// deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe 
// multiverse
// deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe 
// multiverse
// deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted 
// universe multiverse
// deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe 
// multiverse
// deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted 
// universe multiverse
// deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe 
// multiverse
// deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted 
// universe multiverse
// deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe 
// multiverse
// deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted 
// universe multiverse
// #添加清华源 
// deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted 
// universe multiverse
// deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted 
// universe multiverse
// deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main 
// restricted universe multiverse
